package com.qhx.rtkcloud.ntrip;



import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Arrays;
import java.util.concurrent.LinkedBlockingQueue;

import static com.qhx.rtkcloud.ntrip.BaseStationTcpClient.executorService;

public class BaseStationTcpClientSocketQueue {

    private ServerSocket cloudServerSocket;
    private Socket cloudSocket;

    //本地存、云端取
    private LinkedBlockingQueue<byte[]> QueueOne;
    //云端存。本地取
    private LinkedBlockingQueue<byte[]> QueueTwo;

    private ServerSocket localServerSocket;
    private Socket localSocket;


    public BaseStationTcpClientSocketQueue() {
    }

    public BaseStationTcpClientSocketQueue(ServerSocket cloudServerSocket, ServerSocket localServerSocket) {
        this.cloudServerSocket = cloudServerSocket;
        this.localServerSocket = localServerSocket;
        this.QueueOne = new LinkedBlockingQueue<byte[]>();
        this.QueueTwo = new LinkedBlockingQueue<byte[]>();
        //监听对应的端口
        waitCloudTcpClient(cloudServerSocket);
        waitLocalTcpClient(localServerSocket);
    }


    public ServerSocket getCloudServerSocket() {
        return cloudServerSocket;
    }

    public void setCloudServerSocket(ServerSocket cloudServerSocket) {
        this.cloudServerSocket = cloudServerSocket;
    }

    public Socket getCloudSocket() {
        return cloudSocket;
    }

    public void setCloudSocket(Socket cloudSocket) {
        this.cloudSocket = cloudSocket;
    }

    public LinkedBlockingQueue<byte[]> getQueueOne() {
        return QueueOne;
    }

    public void setQueueOne(LinkedBlockingQueue<byte[]> queueOne) {
        QueueOne = queueOne;
    }

    public LinkedBlockingQueue<byte[]> getQueueTwo() {
        return QueueTwo;
    }

    public void setQueueTwo(LinkedBlockingQueue<byte[]> queueTwo) {
        QueueTwo = queueTwo;
    }

    public ServerSocket getLocalServerSocket() {
        return localServerSocket;
    }

    public void setLocalServerSocket(ServerSocket localServerSocket) {
        this.localServerSocket = localServerSocket;
    }

    public Socket getLocalSocket() {
        return localSocket;
    }

    public void setLocalSocket(Socket localSocket) {
        this.localSocket = localSocket;
    }


    private void waitLocalTcpClient(ServerSocket localServerSocket){
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                while (true){
                    try {
                        Socket socket = localServerSocket.accept();
                        socket.setSoTimeout(5000);
                        localSocket = socket;
                        //本地存到QueueOne队列中
                        localStorageToQueueOne(localSocket);
                        //readMessageFromQueueToLocal(localSocket);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

            }
        });
    }

    private void readMessageFromQueueToLocal(Socket localSocket) {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                InputStream inputStream = null;
                try {
                    inputStream = localSocket.getInputStream();
                } catch (IOException e) {
                    closeSocket(localSocket);
                    e.printStackTrace();
                    return;
                }
                byte[] buffer = new byte[10240];
                while (true){
                    try {
                        int read = inputStream.read(buffer);
                        if (read > 0){
                            byte[] bytes = Arrays.copyOfRange(buffer, 0, read);
                            System.out.println("发送到本地的消息"+new String(bytes));
                            QueueTwo.offer(bytes);
                        }
                    } catch (IOException e) {
                        closeSocket(localSocket);
                        e.printStackTrace();
                        break;
                    }
                }
            }
        });
    }

    private void waitCloudTcpClient(ServerSocket cloudServerSocket) {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                while (true){
                    try {
                        Socket socket = cloudServerSocket.accept();
                        cloudSocket = socket;
                        cloudTaskFromQueueOne(cloudSocket);
                        //writeMessageFromClouToQueue(cloudSocket);
                    } catch (IOException e) {
                        cloudSocket = null;
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    private void writeMessageFromClouToQueue(Socket cloudSocket) {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                OutputStream outputStream = null;
                try {
                    outputStream = cloudSocket.getOutputStream();
                } catch (IOException e) {
                    //关闭云端的连接
                    closeSocket(cloudSocket);
                    e.printStackTrace();
                    return;
                }
                while (true){
                    try {
                        byte[] take = QueueTwo.take();
                        System.out.println("取出云端返回的数据"+new String(take));
                        outputStream.write(take);
                        outputStream.flush();
                    } catch (Exception e) {
                        e.printStackTrace();
                        break;
                    }
                }
            }
        });
    }


    //本地存储数据到queueone
    private void localStorageToQueueOne(Socket socket) {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                InputStream inputStream = null;
                try {
                    inputStream = socket.getInputStream();
                } catch (IOException e) {
                    closeSocket(socket);
                    e.printStackTrace();
                    return;
                }
                byte[] buffer = new byte[10240];
                while (true){
                    try {
                        int read = inputStream.read(buffer);
                        if (read > 0){
                            byte[] bytes = Arrays.copyOfRange(buffer, 0, read);
                            System.out.println("接收到本地的消息"+new String(bytes));
                            QueueOne.offer(bytes);
                        }
                    }catch (SocketTimeoutException e){
                    }catch (IOException e) {
                        closeSocket(socket);
                        e.printStackTrace();
                        break;
                    }
                }
            }
        });
    }

    //从本地存储到QueueOne队列中的数据取出发送到云端的socket中
    private void cloudTaskFromQueueOne(Socket socket) {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                OutputStream outputStream = null;
                try {
                    outputStream = socket.getOutputStream();
                } catch (IOException e) {
                    //关闭云端的连接
                    closeSocket(socket);
                    e.printStackTrace();
                    return;
                }
                while (true){
                    try {
                        byte[] take = QueueOne.take();
                        System.out.println("取出云端的数据"+new String(take));
                        outputStream.write(take);
                        outputStream.flush();
                    } catch (Exception e) {
                        e.printStackTrace();
                        break;
                    }
                }
            }
        });
    }


    //关闭云端的连接
    private void closeSocket(Socket socket){
        if (socket != null){
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
